﻿//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EffiProz.Core;
using EffiProz.Core.Lib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using EffiProz.Core.Results;
using EffiProz.Core.Navigators;
using EffiProz.Core.DataTypes;

namespace EffiProz.Test
{
    public static class TestHelper
    {

        static int tableCounter = 0;

        public static string GetNewTableName()
        {
            lock (typeof(TestHelper))
            {
                return "Table" + tableCounter++;
            }
        }

        public static Result ExecuteUpdateSQL_Success(SessionInterface sessionProxy, string sql)
        {
            Result resultOut = Result.newExecuteDirectRequest();
            resultOut.setMainString(sql);
            resultOut.setMaxRows(1000);

            Result resultIn = sessionProxy.execute(resultOut);
            Assert.IsNotNull(resultIn, resultIn.getMainString());
            if (resultIn.isError())
                Assert.Fail(resultIn.getMainString() + " " + resultIn.getException().Message + " " + resultIn.getException().StackTrace);
            Assert.IsFalse(resultIn.isData(), resultIn.getMainString());

            return resultIn;
        }

        //public static Result ExecutePrepareStatement(SessionInterface sessionProxy, string sql, object[] parameters)
        //{
        //    Result resultOut = new Result(ResultConstants.SQLPREPARE);
        //    resultOut.setMainString(sql);
        //    resultOut.setMaxRows(1000);

        //    Result resultIn = sessionProxy.execute(resultOut);
        //    Assert.IsNotNull(resultIn, resultIn.getMainString());
        //    Assert.IsFalse(resultIn.isError(), resultIn.getMainString());
        //    Assert.AreEqual(resultIn.getSize(), 3, resultIn.getMainString());

        //    Iterator it = resultIn.iterator();

        //    object[] row = (object[])it.next();
        //    int statementID = ((Result)row[0]).getStatementID();

        //    row = (object[])it.next();
        //    Result rsmdDescriptor = (Result)row[0];

        //    row = (object[])it.next();
        //    Result pmdDescriptor = (Result)row[0];
        //    int[] parameterTypes = pmdDescriptor.metaData.getParameterTypes();

        //    resultOut = new Result(ResultConstants.SQLEXECUTE, parameterTypes,
        //                       statementID);
        //    resultOut.setMaxRows(1000);
        //    resultOut.setParameterData(parameters);

        //    resultIn = sessionProxy.execute(resultOut);
        //    Assert.IsNotNull(resultIn, resultIn.getMainString());
        //    Assert.IsFalse(resultIn.isError(), resultIn.getMainString());


        //    return resultIn;
        //}

        public static Result GetPrepareStatement(SessionInterface sessionProxy, string sql)
        {
            Result resultOut = Result.newPrepareStatementRequest();
            int queryTimeout = 120;
            int resultSetType = ResultConstants.TYPE_FORWARD_ONLY;
            int resultSetConcurrency = ResultConstants.CONCUR_READ_ONLY;
            int resultSetHoldability = ResultConstants.CLOSE_CURSORS_AT_COMMIT;
            int generatedKeys = ResultConstants.RETURN_NO_GENERATED_KEYS; 
           
            resultOut.setPrepareOrExecuteProperties(sql, 0, 0, 0, queryTimeout,
                resultSetType, resultSetConcurrency, resultSetHoldability,
                generatedKeys,null,null);


            Result resultIn = sessionProxy.execute(resultOut);
            Assert.IsNotNull(resultIn, resultIn.getMainString());
            Assert.IsFalse(resultIn.isError(), resultIn.getMainString());
                   
         
            long statementID = resultIn.getStatementID();

            ResultMetaData rsmdDescriptor = resultIn.metaData;           
            ResultMetaData pmdDescriptor = resultIn.parameterMetaData;

            SqlType[] parameterTypes = pmdDescriptor.getParameterTypes();

            resultOut = Result.newPreparedExecuteRequest(parameterTypes, statementID);
            resultOut.setStatement(resultIn.getStatement());

            return resultOut;
        }

        public static Result ExecutePrepareStatement(SessionInterface sessionProxy, Result resultOut, object[] parameters)
        {
            resultOut.setPreparedExecuteProperties(parameters,1000,1000);            

            Result resultIn = sessionProxy.execute(resultOut);
            Assert.IsNotNull(resultIn, resultIn.getMainString());
            Assert.IsFalse(resultIn.isError(), resultIn.getMainString());

            return resultIn;
        }

        public static Result ExecuteUpdateSQL_Failure(SessionInterface sessionProxy, string sql)
        {
            Result resultOut = Result.newExecuteDirectRequest();
            resultOut.setMainString(sql);
            resultOut.setMaxRows(1000);

            Result resultIn = sessionProxy.execute(resultOut);
            Assert.IsNotNull(resultIn, resultIn.getMainString());
            Assert.IsTrue(resultIn.isError(), resultIn.getMainString());
            Assert.IsFalse(resultIn.isData(), resultIn.getMainString());

            return resultIn;
        }


        public static Result ExecuteSelectSQL(SessionInterface sessionProxy, string sql, int? count)
        {
            Result resultOut = Result.newExecuteDirectRequest();
            resultOut.setMainString(sql);
            resultOut.setMaxRows(1000);

            Result resultIn = sessionProxy.execute(resultOut);

            Assert.IsNotNull(resultIn, resultIn.getMainString());
            Assert.IsFalse(resultIn.isError(), resultIn.getMainString());
            Assert.IsTrue(resultIn.isData(), resultIn.getMainString());
            if (count != null)
                Assert.AreEqual(count, resultIn.getNavigator().size, resultIn.getMainString());

            return resultIn;
        }

        public static void ExecuteSelectSQL_Failure(SessionInterface sessionProxy, string sql)
        {
            Result resultOut = Result.newExecuteDirectRequest();
            resultOut.setMainString(sql);
            resultOut.setMaxRows(1000);

            Result resultIn = sessionProxy.execute(resultOut);

            Assert.IsNotNull(resultIn, resultIn.getMainString());
            Assert.IsTrue(resultIn.isError(), resultIn.getMainString());

        }

        public static string CreateStdSelect(string table, int colCount)
        {
            string sql = "SELECT ";
            for (int i = 0; i < colCount; i++)
            {
                sql += "col" + (i + 1);
                if (i != colCount - 1)
                    sql += " , ";
            }

            return sql + " FROM " + table + " ; ";
        }

        public static string CreateStdInsert(string table, int colCount, params object[] vals)
        {
            string sql = "INSERT INTO " + table + " (";
            for (int i = 0; i < colCount; i++)
            {
                sql += "col" + (i + 1);
                if (i != colCount - 1)
                    sql += " , ";
            }

            sql += " ) VALUES ( ";

            for (int i = 0; i < colCount; i++)
            {
                if (vals[i] == null)
                {
                    sql += " NULL ";
                }
                else if (vals[i] is DateTime)
                    sql += "'" + ((DateTime)vals[i]).ToString("o");
                else if (vals[i] is String)
                    sql += "'" + vals[i];
                else
                    sql += vals[i];

                if (vals[i] is String || vals[i] is DateTime)
                    sql += "'";
                if (i != colCount - 1)
                    sql += " , ";
            }

            return sql + " ); ";
        }



        public static string CreateStdUpdate(string table, string colName, object colVal)
        {
            string sql = "UPDATE " + table + " SET ";

            sql += colName + " = ";

            if (colVal is DateTime)
                sql += "'" + ((DateTime)colVal).ToString("o");
            else if (colVal is String)
                sql += "'" + colVal;
            else
                sql += colVal;
            if (colVal is String || colVal is DateTime)
                sql += "'";

            return sql + " ; ";
        }



        public static void MatchSingleResult(Result resultIn, params object[] vals)
        {
            //Type rtype;
            RowSetNavigator it = resultIn.getNavigator();
            object[] row = (object[])it.getNext();
            for (int j = 0; j < vals.Length; j++)
            {
                if ((vals[j]) is DateTime)
                    Assert.IsTrue((vals[j]).Equals(row[j]));
                else
                    Assert.AreEqual(vals[j], row[j]);
            }
        }



        //public static void MatchSingleResultRow2(Result resultIn, int rowNumber, params object[] vals)
        //{
        //    //Type rtype;
        //    Iterator it = resultIn.iterator();

        //    object[] row = (object[])it.next();
        //    for (int z = 0; z < rowNumber; z++)
        //        row = (object[])it.next();

        //    for (int j = 0; j < vals.Length; j++)
        //    {
        //        //rtype = (vals[j]).GetType();
        //        if ((vals[j]) is DateTime)
        //            Assert.IsTrue((vals[j]).Equals(row[j]));
        //        else
        //            Assert.AreEqual(Convert.ChangeType(vals[j], (row[j]).GetType()), row[j]);
        //    }
        //}

        public static void MatchSingleResults(Result resultIn1, Result resultIn2, int colCount)
        {
            //Type rtype;
            RowSetNavigator it1 = resultIn1.getNavigator();
            RowSetNavigator it2 = resultIn2.getNavigator();

            while (it1.hasNext() && it2.hasNext())
            {
                object[] row1 = (object[])it1.getNext();
                object[] row2 = (object[])it2.getNext();

                for (int j = 0; j < colCount; j++)
                {
                    //rtype = (vals[j]).GetType();
                    if ((row1[j]) is DateTime)
                        Assert.IsTrue((row1[j]).Equals(row2[j]));
                    else
                        Assert.AreEqual(row1[j], row2[j]);
                }
            }
        }




        public static void MatchSingleResultRow(Result resultIn, int rowNumber, params object[] vals)
        {
            //Type rtype;
            RowSetNavigator it = resultIn.getNavigator();
            it.reset();
            object[] row = (object[])it.getNext();
            for (int z = 0; z < rowNumber; z++)
                row = (object[])it.getNext();

            for (int j = 0; j < vals.Length; j++)
            {
                //rtype = (vals[j]).GetType();
                if ((vals[j]) is DateTime)
                    Assert.IsTrue((vals[j]).Equals(row[j]));
                else
                    Assert.AreEqual(vals[j], row[j]);
            }
        }



        public static void MatchMultiResult(Result resultIn, object[,] vals)
        {
            RowSetNavigator it = resultIn.getNavigator();
            //object[] row = null;
            int i = 0;
            while (it.next())
            {
                object[]  row = (object[])it.getNext();
                for (int j = 0; j < resultIn.metaData.getColumnCount(); j++)
                {
                    //rtype = (vals[j]).GetType();
                    if ((row[j]) is DateTime)
                        Assert.IsTrue((row[j]).Equals(vals[i, j]));
                    else
                        Assert.AreEqual(vals[i, j], row[j]);
                }

                i++;
            }
        }

    }
}
